perm filename 106A03[1,RWF] blob sn#749338 filedate 1984-04-03 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00005 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	Strings
C00010 00003	Definitions
C00017 00004	Command:
C00020 00005	A pure function is very easy to test separately from the rest of the program.
C00024 ENDMK
C⊗;
Strings

"What do you get when you cross a Neptunian with a Uranian?  Somebody who
steals space ships, but can't drive them."

What happens when you cross characters and arrays?  Well, on Uranus they tried
to do it by letting arrays be characters.  When they found that to handle
2 by 2 arrays of real numbers as characters they would need more keys on each
keyboard than there are electrons in the universe, they quadrupled the tentacle
tax to pay for it.  The dodecapods rebelled, the government fell, and computers
were outlawed.  We do it differently.

Our written languages are based on sequences of characters: words, sentences,
paragraphs, books, titles, part numbers, license plates, mathematical formulas,
even computer programs.  In Pascal, values like these are kept in arrays of 
characters.  Such arrays are called strings.
Things we might want a computer to do with strings:

(1) Matching.   Let's say that somewhere in a large manuscript I remember
using the phrase "begging the question".  I've learned that I misused the 
term, so I want to find that place.  Probably to find "begging" will suffice.

(2) Substitution.  I have developed a program using shorthand names for the
variables.  Now I wnat to change GW to GROSSWAGES throughout the program.

(3) Alphabetization.  I have an array of strings, each containing the name,
address, and telephone number of one employee.  I want to arrange them in
alphabetical order by name, to print a company directory.

(4) Formatting.  I want to rearrange my manuscript so that paragraphs are
separated by blank lines, and lines are stretched by insertion of spaces to
give straight margins on left and right.  I also want to center the chapter
headings.  Or I want to consistently space and indent a Pascal program.

(5) Interpretation.  I want my program to read phrases like "three thousand
two hundred eighty" on a check, or "gale force winds" on a meteorological
report and translate them into numerical equivalents.

(6) Translation.  I want to provide a word-by-word translation from Spanish
to English.

_String Types_

A string type is a type name that has been defined to be 

	PACKED ARRAY [1..N] OF CHAR

for some integer constant N.  In this text, we will include the value of
N in the names we use for string types; we might define

	TYPE STRING8O = PACKED ARRAY[1..80] OF CHAR;

Such types can be used as types of program variables

	VAR LINE1, LINE2:  STRING80;

or of subprogram parameters

	PROCEDURE CENTER (INPUTLINE: STRING80; VAR OUTPUTLINE: STRING80);

They may not, unfortunately, be used as types of function results in Standard
Pascal.

We can do with strings all the operations implicit in an array of
characters.  To find if a word ends in a vowel we might use the program
fragment: 

	   ...
	   ...
	VAR WORD: STRING20;
	    C: CHAR;
	   ...
	I:=1;
	WHILE WORD[I+1] <> ` ' DO I:=I+1;
	(*NOW WORD[I+1] IS BLANK*)
	C:=WORD[I];
	IF (C=`A') OR ... OR (C=`U') THEN S1 ELSE S2

Additionally, Pascal includes some operations automatically defined for string
types.  If X and Y are of the _same_ string type, they can be tested for
equality and for alphabetical order:

	VAR X,Y: STRING20;
	   ...
	   ...
	IF X=Y THEN WRITE ('SAME WORD')
	ELSE IF X<Y THEN WRITE ('X COMES BEFORE Y')
	ELSE WRITE ('Y COMES BEFORE X')

The tests of alphabetical order are based on the ordering of the
characters, so the results are probably not what you want if the strings
mix capital with lower case letters.  In the ASCII code, for example,
'zebra___' comes before 'AARDVARK', because a lower case letter  z  comes
before an upper case letter A.

You can read to a string variable:

	READ(WORD)

reads one line of an input text file, adds spaces on the right if necessary,
and assigns the resulting string to WORD. If the line is longer than WORD,
the command reads only enough to fill WORD.

The string constants belong to the string types of the same length; you can
assign 

	WORD:='ABCDEFGHIJKLMNOPQRST';

if WORD is of type STRING20.

You can print a string.

	WRITELN(WORD)	prints 	ABCD...RST

The list above contains all of the builtin operations in strings in Pascal.
Comparing it to the long list of functions, operators, and relations on
numbers, you can see that Pascal was designed more to work on numbers than
on strings.  Many Pascal implementations, though, have extensions ("string
packages") to do more, and programmers can design their own procedures to
do common string manipulations.  Here is one to capitalize letters in
string LINE1, putting the result in LINE2:

	PROCEDURE CAPITALIZE(LINE1:STRING80;VAR LINE2: STRING80);
	VAR I:INTEGER;
	BEGIN
	FOR I:=1 TO 80 DO
		IF LINE1[I] IN [`a'..`z'] THEN
		   LINE2[I]:=CHR(LINE1[I] - ORD(`a') + ORD(`A')
		ELSE LINE2[I]:=LINE1[I]
	END;

Definitions

In describing a programming language, it is convenient to factor the definition
into syntax, semantics, and pragmatics.  Syntax is the grammar of the language;
it defines which texts are in the language, and how each program is subdivided
into meaningful parts.  Semantics defines a meaning for each syntactically correct
program, usually by saying what sequence of actions the program performs. 
Pragmatics is concerned with usage and practicality.  Pragmatic details of a
language include the cost in time or money of executing a program, the resources
(such as memory capacity) the computer must have, and the precision with which
calculation is done.

The syntactic definition of the part of Pascal already introduced follows

Program:


	PROGRAM		name		(OUTPUT);


		variable
		declaration     ;


	BEGIN		command         ;	END.



Name:


	letter		letter


			digit


			underline



Variable Declaration:


	VARIABLE	name     	,	:	INTEGER


							REAL

Command:


	WRITE	   (	operand     ,		)


	WRITELN


	FOR variable := expr TO expr DO command


	BEGIN	command		;	END


WRITE(I), where I is an integer-valued expression, prints the value of I,
preceded by enough blanks to make a total of 12 characters.

*************

WRITE(R), where R is a real-valued expression, prints the value of R....

WRITELN by itself adds a carriage return to the output file; subsequent printing
will be on a new line.

WRITE(A,B,C) and WRITELN(A,B,C) abbreviate

	BEGIN		BEGIN
	WRITE(A);	WRITE(A);
	WRITE(B);	WRITE(B);
	WRITE(C);	WRITE(C);
	END		WRITELN
			END

The files created by WRITE and WRITELN should have no more than 132 characters
per line for printing, and no more than 80 per line for display.

Rule of Good Programming Practice: Check that your program, by using WRITELN,
prevents accumulation of oversized output lines.

Expressions include constants and variables.  They also can be built up from smaller 
expressions using standard operations and functions.  If A and B are two 
expressions, and a and b are their respective numerical values, the first column 
in the following table lists expressions that can be built from A and B; the
second column gives the value of the built-up expression


	Expression		Value

	A + B			a + b
	A - B			a - b
	A * B			a x b
	A / B			a / b (an error if b = 0)
	+A			a
	-A			-a
	A DIV B			the integer part of a / b; a and b must be integers
	(A)			a
	ABS(A)			|a|
	SQR (A)			a
	SIN (A)			sine(a)
	COS (A)			cosine(a)
	LN (A)			log (a) (an error if a≤0)
	EXP (A)			e
	SQRT (A)		 a (an error if a<0)
	ARCTAN (A)		tan(a) in the range -π/2, π/2







A pure function is very easy to test separately from the rest of the program.
If it works with numbers, we can try it with constant arguments C1,C2,...Cn
by incorporating the function definition in this program:

PROGRAM....(OUTPUT);

definition of function F;

	BEGIN

	WRITELN(C1,C2,...,Cn,F(C1,C2,...,Cn))

	END.


The penultimate line can be repeated with as many different argument values as
needed, or one can iterate:

FOR I:= 1 to N DO
	
	BEGIN

	READ(X1,X2,...,XN);

	WRITELN(X1,X2,...,XN,F(X1,X2,...,XN)

	END

Such a program is called a driver; its only purpose is to test a pure function on
data for which the correct result is known.

Conversely, it is easy to test the main program without the correct definition of
the pure function, replacing the function's definition by some easy function.
If the main program is designed to form the sum F(1)+F(2)+...+F(100), and the
correct definition of F is difficult, we can test the summation and the printing
format by using the function F(X)=X, this way:

PROGRAM P(OUTPUT);

VAR

FUNCTION F(I:INTEGER:REAL;

	BEGIN

	F:=I

	END;

BEGIN

SUM:=0.0

FOR J:= 1 TO 100 DO

	SUM:= SUM + F(J);

WRITELN SUM:6:2

END.


If the program prints 5050.00, we know that the main program is in good shape.
We have tested it using a stub in place of the correct subprogram; a stub goes
through the same motions as the absent subprogram, without necessarily giving
correct answers.

If the test of the master program requires that the subprogram give correct
answers, we can still test with a stub, but the stub now asks the user for help.
The declaration of the stub looks like:

FUNCTION F(X,Y:REAL):REAL;

BEGIN

WRITELN(TTY,'WHAT IS F IF X AND Y ARE',X,Y);

READ(TTY,X,Y)

(* FOR A MORE RELIABLE TERMINAL INPUT *)

(* SEE SECTION ON FILES               *)

END


Every part of a program under development can be tested separately, by using a
driver to substitute for its master program, and stubs to substitute for its
subprograms.  This technique allows a team to subdivide a programming project
in such a way that no bottlenecks impede the testing.

Reference:  Aron, The Programs Development Process.